﻿using System.Collections.Generic;
using System.Web.Mvc;
using NUnit.Framework;
using WeBlog.Controllers;
using WeBlog.DataContext;
using WeBlog.Interfaces;
using WeBlog.Models;
using WeBlog.Repositories;
using WeBlog.Tests.Helpers;

namespace WeBlog.Tests.Controllers
{
    [TestFixture]
    public class TagControllerTests
    {
        private IUnitOfWork _unitOfWork;
        private Tag _fakeTag;

        [SetUp]
        public void Setup()
        {
            _unitOfWork = new InMemoryUnitOfWork();
            var tagRepository = new TagRepository(_unitOfWork);
            _fakeTag = new Tag { TagId = 1, Name = "Hello World", Posts = new List<Post>() { } };
            tagRepository.Add(_fakeTag);
        }

        [Test]
        public void Manage_Action_Should_Return_Valid_View()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);
            controller.SetFakeControllerContext();

            //Act
            var result = controller.Manage(new GridSettings()) as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(ManageTagsViewModel), result.ViewData.Model);
        }

        [Test]
        public void Details_Action_Should_Return_Valid_View()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);
            controller.SetFakeControllerContext();

            //Act
            var result = controller.Details(new GridSettings(), "Hello World") as ViewResult;

            //Assert
            Assert.IsNotNull(result.ViewData.Model);
            Assert.IsInstanceOf(typeof(TagViewModel), result.ViewData.Model);
        }

        [Test]
        public void Details_Action_Should_Throw_NotFoundException_For_Invalid_Tag()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);

            //Act            

            //Assert
            Assert.Throws(typeof(NotFoundException), () => controller.Details(new GridSettings(), "the tag does not exist"));
        }

        [Test]
        public void Create_Action_Should_Add_Tag()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);

            //Act
            var result = controller.Create("MyNewTag") as JsonResult;         

            //Assert
            Assert.IsTrue((result.Data as JsonResponse).Success);
            Assert.IsNotNull(new TagRepository(_unitOfWork).FindByName("MyNewTag"));
        }

        [Test]
        public void Create_Action_Should_Return_JsonResult_SuccessFalse_For_Empty_Tag()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);

            //Act
            var result = controller.Create("") as JsonResult;

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
        }

        [Test]
        public void Create_Action_Should_Return_JsonResult_SuccessFalse_For_Existing_Tag()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);

            //Act
            var result = controller.Create("Hello World") as JsonResult;

            //Assert
            Assert.IsFalse((result.Data as JsonResponse).Success);
        }

        [Test]
        public void Delete_Action_Should_Remove_Records()
        {
            //Arrange
            var tagRepository = new TagRepository(_unitOfWork);
            var controller = new TagController(_unitOfWork);
            var tag1 = new Tag { TagId = 2, Name = "Hello World2", Posts = new List<Post>() { new Post() { Slug = "Hello", PostId = 1, PostComments = new List<PostComment>(), Tags = new List<Tag>() { new Tag() { TagId = 4, Name = "Hello World4", Posts = new List<Post>() } } } } };
            var tag2 = new Tag { TagId = 3, Name = "Hello World3", Posts = new List<Post>() };
            tagRepository.Add(tag1);
            tagRepository.Add(tag2);
            int[] tagIds = new int[2] { 2, 3 };

            //Act
            var result = controller.Delete(tagIds) as RedirectToRouteResult;

            //Assert
            Assert.IsNotNull(result);
            Assert.Null(tagRepository.Find(2));
            Assert.Null(tagRepository.Find(3));
        }

        [Test]
        public void Edit_Action_Should_Update_Record()
        {
            //Arrange
            const string newTagName = "MyUpdatedTag";
            var tagRepository = new TagRepository(_unitOfWork);
            var controller = new TagController(_unitOfWork);

            //Act
            var result = controller.Edit(1, newTagName) as JsonResult;

            //Assert
            Assert.IsTrue(((dynamic)result.Data).Success);
            Assert.AreEqual(newTagName, tagRepository.Find(1).Name);
        }

        [Test]
        public void Edit_Action_Should_Return_JsonResult_SuccessFalse_When_Tag_Is_Empty()
        {
            //Arrange
            const string newTagName = "";
            var controller = new TagController(_unitOfWork);

            //Act
            var result = controller.Edit(1, newTagName) as JsonResult;

            //Assert
            Assert.IsFalse(((dynamic)result.Data).Success);
        }

        [Test]
        public void TagSuggestion_Action_Should_Return_Tags_With_The_Same_Prefix()
        {
            //Arrange
            var controller = new TagController(_unitOfWork);

            //Act
            var result = controller.TagSuggestion("He") as JsonResult;

            //Assert
            Assert.AreEqual("Hello World", ((dynamic)result.Data)[0]);
        }
    }
}
